package mk.edu.ii.navigatemacedonia;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class ServiceConnect {
	private static ArrayList<Site> sites;

	public static String SITE_NAME = "SiteName";
	public static String SITE_DESCRIPTION = "SiteDescription";
	public static String SITE_CATEGORY = "SiteCategory";
	public static String SITE_IMAGE = "SiteImage";
	public static String SITE_LONGITUDE = "SiteLongitude";
	public static String SITE_LATITUDE = "SiteLatitude";
	public static String SITE_SUBCATEGORY = "SiteSubCategory";
	public static String SITE_RATING = "SiteRating";
	public static String SITE_ID = "SiteID";

	public static String UPDATE_CATEGORY_ID = "Category_ID";
	public static String UPDATE_SUBCATEGORY_ID = "SubCategory_ID";
	public static String UPDATE_SUBCATEGORY_NAME = "subcategory";
	
	private static int timeoutConnection = 10000;

	View v;
	private Context context;
	private static Handler handler;
	private static HttpClient httpclient;
	
	private static ServiceConnect serviceConnect= null;

	private ServiceConnect(Context context, Handler handler) {
		this.context = context;
		ServiceConnect.handler = handler;
	}
	
	public static ServiceConnect getInstance(Context context, Handler handler){
		if(serviceConnect==null){
			serviceConnect = new ServiceConnect(context, handler);
		}
		return serviceConnect;
	}

	public ArrayList<Site> getSitesFromService(Handler handler, Double longitude,
			Double latitude, Integer radius, String category,
			String subcategory, String searchText) {

		ServiceConnect.handler = handler;

		return getSitesRequest(ServiceURL.getSitesMethodURL(longitude,
				latitude, radius, category, subcategory, searchText));
	}

	// connecting to service and put information into ArrayList of Sites
	private ArrayList<Site> getSitesRequest(String GET_URL) {

		try {
			HttpResponse response = getResponse(GET_URL);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity entity = response.getEntity();

				if (entity != null) {
					InputStream instream = entity.getContent();
					String result = convertStreamToString(instream);

					JSONObject json = new JSONObject(result);
					parseJsonToSites(json);

					instream.close();
				}
			} else {
				throw new HttpResponseException(response.getStatusLine()
						.getStatusCode(), response.getStatusLine()
						.getReasonPhrase());
			}
		} catch (HttpResponseException hre) {
			showResponseStatusMessage(hre);
			hre.printStackTrace();
			return null;
		} catch (ClientProtocolException cpe) {
			showToast(context, context.getResources().getString(
					R.string.connection_problem));
			cpe.printStackTrace();
			return null;
		} catch (IOException ioe) {
			showToast(context, context.getResources().getString(
					R.string.connection_network_problem));
			ioe.printStackTrace();
			return null;
		} catch (JSONException jsone) {
			showToast(context, context.getResources().getString(
					R.string.server_internal_problem));
			jsone.printStackTrace();
			return null;
		}
		return sites;
	}

	

	public boolean rateSite(String userkey, String siteID, Float siteRating) {
		// Parametri za Timeout
		HttpParams httpParameters = new BasicHttpParams();
		// Set the timeout in milliseconds until a connection is established.
		
		HttpConnectionParams.setConnectionTimeout(httpParameters,
				timeoutConnection);

		// Set the default socket timeout (SO_TIMEOUT)
		// in milliseconds which is the timeout for waiting for data.

		HttpConnectionParams.setSoTimeout(httpParameters, timeoutConnection);

		// inicijalizacija na http client

		httpclient = new DefaultHttpClient(httpParameters);

		HttpPost httppost = new HttpPost(ServiceURL.rateURL(userkey, siteID,
				siteRating.toString()));
		
		try {
			int statuscode = httpclient.execute(httppost).getStatusLine()
					.getStatusCode();
			
			if (statuscode == 200)
				showToast(context, context.getResources().getString(
						R.string.rate_succesfull));
			else
				showToast(context, context.getResources().getString(
						R.string.rate_not_succesfull));
		} catch (Exception e) {
			showToast(context, context.getResources().getString(
					R.string.connection_problem));
		}

		return true;
	}

	public String login(String username, String password) {
		String key = new String();
		try {
			HttpResponse response = getResponse(ServiceURL.loginMethodURL(
					username, password));
			if (response != null) {
				if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					HttpEntity entity = response.getEntity();

					if (entity != null) {
						InputStream instream = entity.getContent();
						String result = convertStreamToString(instream);

						JSONObject json = new JSONObject(result);
						key = json.get("value").toString();
						return key;
					}

				} else {
					throw new HttpResponseException(response.getStatusLine()
							.getStatusCode(), response.getStatusLine()
							.getReasonPhrase());
				}
			}
		} catch (HttpResponseException hre) {
			showResponseStatusMessage(hre);
			hre.printStackTrace();
		} catch (ClientProtocolException cpe) {
			showToast(context, context.getResources().getString(
					R.string.connection_problem));
			cpe.printStackTrace();
		} catch (IOException ioe) {
			showToast(context, context.getResources().getString(
					R.string.sc_not_found));
			ioe.printStackTrace();
		} catch (JSONException jsone) {
			showToast(context, context.getResources().getString(
					R.string.server_internal_problem));
			jsone.printStackTrace();
		}
		return null;

	}
	
	public void subcategoryUpdate(ContentResolver cr, String userkey,
			Context context) {

		try {
			HttpResponse response = getResponse(ServiceURL.updateURL(userkey));
			if (response.getStatusLine().getStatusCode() == 200) {
				InputStream instream = response.getEntity().getContent();
				String result = convertStreamToString(instream);

				JSONObject json = new JSONObject(result);
				JSONArray subcategoryArray = new JSONArray();
				subcategoryArray = json.getJSONArray("subcategorys");

				ContentValues values = new ContentValues();
				cr.delete(NMContentProvider.CONTENT_URI, null, null);

				for (int i = 0; i < subcategoryArray.length(); i++) {
					String categoryID = subcategoryArray.getJSONObject(i)
							.optString("Category_ID");
					String subcategoryName = subcategoryArray.getJSONObject(i)
							.optString("subcategory");
					int subcategoryID = subcategoryArray.getJSONObject(i)
							.optInt("SubCategory_ID");

					values.put(NMContentProvider.KEY_ID, subcategoryID);
					values.put(NMContentProvider.KEY_SUBCATEGORY,
							subcategoryName);
					values.put(NMContentProvider.KEY_CATEGORY, categoryID);
					// Log.i("UPDATE",cr.insert(NMContentProvider.CONTENT_URI,
					// values).toString());
					cr.insert(NMContentProvider.CONTENT_URI, values);
				}
				Log.d("Navigate Macedonia", "Update subcategorys succesfull");

			}
		} catch (HttpResponseException hre) {
			showResponseStatusMessage(hre);
			hre.printStackTrace();
		} catch (ClientProtocolException cpe) {
			showToast(context, context.getResources().getString(
					R.string.connection_problem));
			cpe.printStackTrace();
		} catch (IOException ioe) {
			showToast(context, context.getResources().getString(
					R.string.connection_network_problem));
			ioe.printStackTrace();
		} catch (JSONException jsone) {
			showToast(context, context.getResources().getString(
					R.string.server_internal_problem));
			jsone.printStackTrace();
		}
	}

	public static void showToast(final Context context, final String msg) {
		handler.post(new Runnable() {

			@Override
			public void run() {
				int duration = Toast.LENGTH_SHORT;
				Toast toast = Toast.makeText(context, msg, duration);
				toast.show();

			}
		});
	}

	private void parseJsonToSites(JSONObject json) throws IOException,
			JSONException {

		JSONArray sitesArray = new JSONArray();
		sitesArray = json.getJSONArray("sites");

		sites = new ArrayList<Site>();
		// Parsing
		for (int i = 0; i < sitesArray.length(); i++) {
			JSONObject siteJson = sitesArray.getJSONObject(i);
			String id = siteJson.optString(SITE_ID, "0");
			String name = siteJson.optString(SITE_NAME);
			String description = siteJson.optString(SITE_DESCRIPTION);
			String image = siteJson.optString(SITE_IMAGE);
			String category = siteJson.optString(SITE_CATEGORY);
			String longitude = siteJson.optString(SITE_LONGITUDE);
			String latitude = siteJson.optString(SITE_LATITUDE);
			String subCategory = siteJson.optString(SITE_SUBCATEGORY);
			String rating = siteJson.optString(SITE_RATING);
			Site site = new Site(id, name, description, category, image, longitude,
					latitude, subCategory, rating);
			sites.add(site);
		}
	}

	private HttpResponse getResponse(String getURL)
			throws ClientProtocolException, IOException {

		Log.d("HTTP request:", getURL);
		// inicijalizacija na http GET metod
		HttpGet httpget = new HttpGet(getURL);

		// Parametri za Timeout
		HttpParams httpParameters = new BasicHttpParams();
		// Set the timeout in milliseconds until a connection is
		// established.
		
		HttpConnectionParams.setConnectionTimeout(httpParameters,
				timeoutConnection);

		// Set the default socket timeout (SO_TIMEOUT)
		// in milliseconds which is the timeout for waiting for data.
		
		HttpConnectionParams.setSoTimeout(httpParameters, timeoutConnection);

		// inicijalizacija na http client

		httpclient = new DefaultHttpClient(httpParameters);

		return httpclient.execute(httpget);
	}

	public int getCategoryID(String category, Context context) {
		ArrayAdapter<CharSequence> array = ArrayAdapter.createFromResource(
				context, R.array.category, 1);
		return array.getPosition(category);
	}
	
	// converting HTTP respond stream from service to String
	private static String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

	private void showResponseStatusMessage(HttpResponseException hre) {

		switch (hre.getStatusCode()) {
		case HttpStatus.SC_FORBIDDEN:
			showToast(context, context.getResources().getString(
					R.string.sc_forbidden));
			break;
		case HttpStatus.SC_NOT_FOUND:
			showToast(context, context.getResources().getString(
					R.string.sc_not_found));
			break;
		case HttpStatus.SC_REQUEST_TIMEOUT:
			showToast(context, context.getResources().getString(
					R.string.sc_connect_failed));
		default:
			showToast(context, context.getResources().getString(
					R.string.connection_problem)
					+ "(Status code:"
					+ hre.getStatusCode()
					+ ")"
					);
			break;
		}
	}
}
